package com.gzdh.dishrecognition.ui.dialog.identify;

import android.Manifest;
import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.pm.PackageManager;
import android.graphics.Color;
import android.graphics.Rect;
import android.graphics.SurfaceTexture;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.CaptureResult;
import android.hardware.camera2.TotalCaptureResult;
import android.hardware.camera2.params.StreamConfigurationMap;
import android.os.Bundle;
import android.util.Log;
import android.util.Range;
import android.util.Size;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.ScaleGestureDetector;
import android.view.Surface;
import android.view.TextureView;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.BaseAdapter;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.app.ActivityCompat;
import androidx.fragment.app.DialogFragment;

import com.gzdh.dishrecognition.R;
import com.gzdh.dishrecognition.config.IdfConst;
import com.gzdh.dishrecognition.ui.view.AutoFitTextureView;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import butterknife.BindView;
import butterknife.ButterKnife;

public class CameraSettingDialogFragment extends DialogFragment {

    private static final String TAG = "CameraSetting";
    private Context mContext;

    CameraManager cameraManager;//相机管理类
    CameraDevice cameraDevice;//相机设备类
    CameraCaptureSession cameraCaptureSession;//相机会话类
    Surface previewSurface;
    CameraCharacteristics mCameraCharacteristics;
    String cameraId;//相机id
    List<Size> outputSizes;//相机输出尺寸
    Size previewSize;//预览尺寸
    Range<Integer>[] fpsRanges;

    private SizeAdapter sizeAdapter;

    private float zoomLevel = 1f;

    private boolean cameraInit;

    private AutoFitTextureView previewView;

    private RelativeLayout titleRv;
    private TextView cameraSelector;
    private TextView cameraSizeSelector;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setHasOptionsMenu(true);
        setRetainInstance(true);
//        systemSettingObject = getArguments().getParcelable(SystemSettingDialogFragment.SYSTEM_SETTING);
    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        mContext = inflater.getContext();
        View view = getViews();
        view.setFocusable(true);
        view.setFocusableInTouchMode(true);
        getDialog().requestWindowFeature(Window.FEATURE_NO_TITLE);
        initCameraView();
        return view;
    }

    private View getViews() {
        RelativeLayout relativeLayout = new RelativeLayout(mContext);
        relativeLayout.setLayoutParams(new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
        relativeLayout.addView(getTitle());
        relativeLayout.addView(getBody());
        return relativeLayout;
    }


    private View getTitle() {
        titleRv = new RelativeLayout(mContext);
        titleRv.setId(View.generateViewId());
        titleRv.setLayoutParams(new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));

        TextView cameraSettingTitle = new TextView(mContext);
        RelativeLayout.LayoutParams rvLayout = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        rvLayout.addRule(RelativeLayout.CENTER_VERTICAL);
        cameraSettingTitle.setLayoutParams(rvLayout);
        cameraSettingTitle.setPadding(20, 20, 20, 20);
        cameraSettingTitle.setText("摄像头设置");
        cameraSettingTitle.setTextSize(TypedValue.COMPLEX_UNIT_SP, 20);
        titleRv.addView(cameraSettingTitle);

        LinearLayout linearLayout = new LinearLayout(mContext);
        rvLayout = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        rvLayout.addRule(RelativeLayout.CENTER_VERTICAL);
        rvLayout.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
        linearLayout.setLayoutParams(rvLayout);
        linearLayout.setOrientation(LinearLayout.HORIZONTAL);
        titleRv.addView(linearLayout);

        cameraSelector = new TextView(mContext);
        rvLayout = new RelativeLayout.LayoutParams(140, 40);
        rvLayout.addRule(RelativeLayout.CENTER_VERTICAL);
        rvLayout.setMargins(10, 10, 10, 10);
        cameraSelector.setLayoutParams(rvLayout);
        cameraSelector.setText("未设置");
        cameraSelector.setTextColor(Color.WHITE);
        cameraSelector.setBackground(mContext.getResources().getDrawable(R.drawable.bg_btn_pay));
        cameraSelector.setPadding(17, 7, 17, 7);
        linearLayout.addView(cameraSelector);

        cameraSizeSelector = new TextView(mContext);
        rvLayout = new RelativeLayout.LayoutParams(140, 40);
        rvLayout.addRule(RelativeLayout.CENTER_VERTICAL);
        rvLayout.setMargins(10, 10, 10, 10);
        cameraSizeSelector.setText("未设置");
        cameraSizeSelector.setBackground(mContext.getResources().getDrawable(R.drawable.bg_btn_pay));
        cameraSizeSelector.setLayoutParams(rvLayout);
        cameraSizeSelector.setTextColor(Color.WHITE);
        cameraSizeSelector.setPadding(17, 7, 17, 7);
        linearLayout.addView(cameraSizeSelector);

        TextView saveBut = new TextView(mContext);
        rvLayout = new RelativeLayout.LayoutParams(140, 40);
        rvLayout.addRule(RelativeLayout.CENTER_VERTICAL);
        rvLayout.setMargins(10, 10, 10, 10);
        saveBut.setText("保存");
        saveBut.setBackground(mContext.getResources().getDrawable(R.drawable.bg_btn_pay));
        saveBut.setLayoutParams(rvLayout);
        saveBut.setGravity(Gravity.CENTER);
        saveBut.setTextColor(Color.WHITE);
        saveBut.setPadding(17, 7, 17, 7);
        linearLayout.addView(saveBut);
        saveBut.setOnClickListener(view -> {
            IdfConst.getInstance().setWidth(previewSize.getWidth());
            IdfConst.getInstance().setHeight(previewSize.getHeight());
            IdfConst.getInstance().setCameraId(cameraId);
            dismiss();
        });

        return titleRv;
    }


    private View getBody() {

        FrameLayout frameLayout = new FrameLayout(mContext);
        RelativeLayout.LayoutParams rvLinear = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
        rvLinear.addRule(RelativeLayout.BELOW, titleRv.getId());
        rvLinear.setMargins(0, 20, 0, 0);
        frameLayout.setLayoutParams(rvLinear);

        View line = new View(mContext);
        RelativeLayout.LayoutParams rvLayout = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 1);
        rvLayout.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
        line.setLayoutParams(rvLayout);
        line.setBackgroundColor(Color.rgb(220, 220, 220));
        frameLayout.addView(line);
        previewView = new AutoFitTextureView(mContext);
        rvLinear = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
        rvLinear.setMargins(0, 10, 0, 10);
        previewView.setLayoutParams(rvLinear);
        frameLayout.addView(previewView);
        return frameLayout;
    }

    private void initCameraView() {
        try {
            if (!(cameraInit = initCamera())) {
                previewView.setVisibility(View.INVISIBLE);
                Toast.makeText(getActivity(), "未检测到摄像头！", Toast.LENGTH_SHORT).show();
            }
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }

        previewView.setSurfaceTextureListener(new TextureView.SurfaceTextureListener() {
            @Override
            public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
                Log.i(TAG, " onSurfaceTextureAvailable width=" + width + " height=" + height);
                if (cameraInit)
                    openCamera();
            }

            @Override
            public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
                Log.i(TAG, " onSurfaceTextureSizeChanged width=" + width + " height=" + height);
//                autoFocusCamera();
            }

            @Override
            public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
                Log.i(TAG, " onSurfaceTextureDestroyed");
                releaseCamera();
                return false;
            }

            @Override
            public void onSurfaceTextureUpdated(SurfaceTexture surface) {
//                Log.i(TAG, " onSurfaceTextureUpdated");
            }
        });
        previewView.setScaleDetector(new ScaleGestureDetector(getActivity(), new ScaleGestureDetector.SimpleOnScaleGestureListener() {
            @Override
            public boolean onScale(ScaleGestureDetector detector) {
                int mScaleFactor = (int) detector.getScaleFactor();
                Float maxZoom = mCameraCharacteristics.get(CameraCharacteristics.SCALER_AVAILABLE_MAX_DIGITAL_ZOOM);
                if (cameraDevice != null && cameraInit) {
                    if (mScaleFactor == 1) {
                        if (zoomLevel < maxZoom) zoomLevel += 0.01;
                    } else if (mScaleFactor == 0) {
                        if (zoomLevel > 1) zoomLevel -= 0.01;
                    }
                    updateCameraCaptureSession();
                }
                return true;
            }

        }));
    }

    private boolean initCamera() throws CameraAccessException {
        cameraManager = (CameraManager) getActivity().getSystemService(Context.CAMERA_SERVICE);
        String[] cameraIdList = cameraManager.getCameraIdList();
        if (cameraIdList.length == 0) {
            return false;
        }

        cameraSelector.setOnClickListener(view -> {
            AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
            builder.setTitle("驱动选择");
            final Map<String, String> map = new LinkedHashMap<>();
            for (int i = 0; i < cameraIdList.length; i++) {
                map.put(cameraIdList[i], cameraIdList[i]);
            }
            final String[] keysTemp = new String[cameraIdList.length];
            final String[] keys = map.keySet().toArray(keysTemp);
            builder.setItems(keys, new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    if (cameraId == cameraIdList[which]) return;
                    releaseCamera();

                    cameraId = cameraIdList[which];//默认使用后置相机
                    //获取指定相机的输出尺寸列表，降序排序
                    outputSizes = getCameraOutputSizes(cameraId);
                    cameraSizeSelector.setText("未选择");
                    //初始化预览尺寸
                    previewSize = outputSizes.get(0);
                    zoomLevel = 1f;
//                if (x_reverse) {
//                    previewView.setScaleX(-1f);
//                }
//                if (y_reverse) {
//                    previewView.setScaleY(-1f);
//                }
                    openCamera();

                }
            });
            builder.show();
        });

        cameraId = IdfConst.getInstance().getCameraId();
        if (cameraId == null) {
            cameraId = cameraIdList[0];//默认使用后置相机
        }
//        if (x_reverse) {
//            previewView.setScaleX(-1f);
//        }
//        if (y_reverse) {
//            previewView.setScaleY(-1f);
//        }

        //获取指定相机的输出尺寸列表，降序排序
        outputSizes = getCameraOutputSizes(cameraId);
        cameraSizeSelector.setOnClickListener(view -> {
            AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
            builder.setTitle("分辨率设置");
            final Map<String, Size> map = new LinkedHashMap<>();
            for (int i = 0; i < outputSizes.size(); i++) {
                map.put(outputSizes.get(i).getWidth() + "x" + outputSizes.get(i).getHeight(), outputSizes.get(i));
            }
            final String[] keysTemp = new String[outputSizes.size()];
            final String[] keys = map.keySet().toArray(keysTemp);
            builder.setItems(keys, new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    Size state = map.get(keys[which]);
//                if (previewSize == outputSizes.get(position)) return;
                    releaseCamera();
                    //初始化预览尺寸
                    previewSize = state;
                    zoomLevel = 1f;
                    openCamera();
                }
            });
            builder.show();
        });
        previewSize = new Size(IdfConst.getInstance().getWidth(), IdfConst.getInstance().getHeight());


        if (previewSize == null) {
            //初始化预览尺寸
            previewSize = outputSizes.get(0);
        }

        //获取相机帧数范围
        CameraCharacteristics characteristics = cameraManager.getCameraCharacteristics(cameraId);
        fpsRanges = characteristics.get(CameraCharacteristics.CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES);
        Log.d("FPS", "SYNC_MAX_LATENCY_PER_FRAME_CONTROL: " + Arrays.toString(fpsRanges));

        zoomLevel = 1;
        return true;
    }

    private void releaseCamera() {
        if (cameraCaptureSession != null)
            cameraCaptureSession.close();
        if (cameraDevice != null)
            cameraDevice.close();
    }

    /**
     * 根据输出类获取指定相机的输出尺寸列表，降序排序
     *
     * @param cameraId 相机id
     * @return
     */
    public List<Size> getCameraOutputSizes(String cameraId) {
        try {
            CameraCharacteristics characteristics = cameraManager.getCameraCharacteristics(cameraId);
            StreamConfigurationMap configs = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
            Size[] outputSizes = configs.getOutputSizes(SurfaceTexture.class);
            List<Size> sizes = new ArrayList<>();
            boolean openfaceClass = false;
            try {
                Class.forName("com.baidu.idl.main.facesdk.registerlibrary.user.manager.FaceSDKManager");
                openfaceClass = true;
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
//            boolean openface = systemSettingObject == null ? false : systemSettingObject.isOpenface();
            boolean openface = false;
            for (int i = outputSizes.length - 1; i >= 0; i--) {
                Size size = outputSizes[i];
                if (openface && openfaceClass && size.getWidth() * size.getHeight() > 1280 * 720) {
                    continue;
                }
                sizes.add(size);
            }
            Collections.sort(sizes, (o1, o2) -> o2.getWidth() * o2.getHeight() - o1.getWidth() * o1.getHeight());
            Collections.reverse(sizes);
            return sizes;
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }

        return null;
    }


    @SuppressLint("SetTextI18n")
    private void openCamera() {
        try {
            if (previewSize != null) {
                cameraSizeSelector.setText(previewSize.getWidth() + "X" + previewSize.getHeight());
            }
            if (cameraId != null) {
                cameraSelector.setText(cameraId);
            }
            //打开相机
            if (ActivityCompat.checkSelfPermission(getActivity(), Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
                return;
            }
            mCameraCharacteristics = cameraManager.getCameraCharacteristics(this.cameraId);
            cameraManager.openCamera(cameraId,
                    new CameraDevice.StateCallback() {
                        @Override
                        public void onOpened(CameraDevice camera) {
                            if (camera == null) {
                                return;
                            }
                            cameraDevice = camera;
                            try {
                                //创建相机预览 session
                                createPreviewSession();
                            } catch (CameraAccessException e) {
                                e.printStackTrace();
                            }
                        }

                        @Override
                        public void onDisconnected(CameraDevice camera) {
                            //释放相机资源
                            releaseCamera();
                        }

                        @Override
                        public void onError(CameraDevice camera, int error) {
                            //释放相机资源
                            releaseCamera();
                        }
                    },
                    null);
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }


    private void createPreviewSession() throws CameraAccessException {
        if (previewView == null) return;
        //关闭之前的会话
        if (cameraCaptureSession != null)
            cameraCaptureSession.close();
        //根据TextureView 和 选定的 previewSize 创建用于显示预览数据的Surface
        SurfaceTexture surfaceTexture = previewView.getSurfaceTexture();
        surfaceTexture.setDefaultBufferSize(previewSize.getWidth(), previewSize.getHeight());//设置SurfaceTexture缓冲区大小
        previewView.setAspectRation(previewSize.getWidth(), previewSize.getHeight());
        //获取 ImageReader 和 surface
        previewSurface = new Surface(surfaceTexture);
        //创建预览session
        cameraDevice.createCaptureSession(Arrays.asList(previewSurface),
                new CameraCaptureSession.StateCallback() {
                    @Override
                    public void onConfigured(CameraCaptureSession session) {
                        cameraCaptureSession = session;
                        try {
                            //构建预览捕获请求
                            CaptureRequest.Builder builder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
                            builder.addTarget(previewSurface);//设置 previewSurface 作为预览数据的显示界面
                            Rect zoomRect = getZoomRect();
                            if (zoomRect != null) {
                                //you can try to add the synchronized object here
                                zoomRect.left = 500;
                                zoomRect.top = 500;
                                Log.e(TAG, zoomRect.toString());
                                builder.set(CaptureRequest.SCALER_CROP_REGION, zoomRect);
                            }
                            CaptureRequest captureRequest = builder.build();
                            //设置重复请求，以获取连续预览数据
                            session.setRepeatingRequest(captureRequest, new CameraCaptureSession.CaptureCallback() {
                                        @Override
                                        public void onCaptureProgressed(CameraCaptureSession session, CaptureRequest request, CaptureResult partialResult) {
                                            super.onCaptureProgressed(session, request, partialResult);
                                        }

                                        @Override
                                        public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) {
                                            super.onCaptureCompleted(session, request, result);
                                        }
                                    },
                                    null);
                        } catch (CameraAccessException e) {
                            e.printStackTrace();
                        } catch (IllegalStateException e) {
                            e.printStackTrace();
                        }
                    }

                    @Override
                    public void onConfigureFailed(CameraCaptureSession session) {

                    }
                },
                null);
    }

    /**
     * 获取缩放矩形
     **/
    private Rect getZoomRect() {
        float maxZoom = mCameraCharacteristics.get(
                CameraCharacteristics.SCALER_AVAILABLE_MAX_DIGITAL_ZOOM);
        Rect activeRect = mCameraCharacteristics.get(CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE);
        Log.d("maxZoom", maxZoom + "");
        int minW = (int) (activeRect.width() / maxZoom);
        int minH = (int) (activeRect.height() / maxZoom);
        int difW = activeRect.width() - minW;
        int difH = activeRect.height() - minH;

        // When zoom is 1, we want to return new Rect(0, 0, width, height).
        // When zoom is maxZoom, we want to return a centered rect with minW and minH
        if (zoomLevel < 1) zoomLevel = 1;
        if (zoomLevel > maxZoom) zoomLevel = maxZoom;
        int cropW = (int) (difW * (zoomLevel - 1) / (maxZoom - 1) / 2F);
        int cropH = (int) (difH * (zoomLevel - 1) / (maxZoom - 1) / 2F);
        return new Rect(cropW, cropH, activeRect.width() - cropW, activeRect.height() - cropH);
    }

    class SizeAdapter extends BaseAdapter {
        private final Context mContext;

        SizeAdapter(Context context) {
            mContext = context;
        }

        @Override
        public int getCount() {
            return outputSizes == null ? 0 : outputSizes.size();
        }

        @Override
        public Object getItem(int position) {
            return outputSizes.get(position);
        }

        @Override
        public long getItemId(int position) {
            return 0;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            ViewHolder holder;
            if (convertView != null && convertView.getTag() != null) {
                holder = (ViewHolder) convertView.getTag();
            } else {
                convertView = View.inflate(mContext, R.layout.my_camera_simple_size_item, null);
                holder = new ViewHolder(convertView);
                convertView.setTag(holder);
            }

            Size item = (Size) getItem(position);
            holder.text1.setText(item.toString());
            return convertView;
        }

        class ViewHolder {
            @BindView(android.R.id.text1)
            TextView text1;

            public ViewHolder(View view) {
                ButterKnife.bind(this, view);
            }
        }
    }

    public void updateCameraCaptureSession() {
        try {
            //构建预览捕获请求
            CaptureRequest.Builder builder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
            builder.addTarget(previewSurface);//设置 previewSurface 作为预览数据的显示界面
            Rect zoomRect = getZoomRect();
            if (zoomRect != null) {
                //you can try to add the synchronized object here
                Log.e(TAG, zoomRect.toString());
                builder.set(CaptureRequest.SCALER_CROP_REGION, zoomRect);
            }
            // 设置预览画面的帧率 视实际情况而定选择一个帧率范围
            builder.set(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE, fpsRanges[0]);
            CaptureRequest captureRequest = builder.build();
            //设置重复请求，以获取连续预览数据
            cameraCaptureSession.setRepeatingRequest(captureRequest, new CameraCaptureSession.CaptureCallback() {
                        @Override
                        public void onCaptureProgressed(CameraCaptureSession session, CaptureRequest request, CaptureResult partialResult) {
                            super.onCaptureProgressed(session, request, partialResult);
                        }

                        @Override
                        public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) {
                            super.onCaptureCompleted(session, request, result);
                        }
                    },
                    null);
            Log.e(TAG, "zoomLevel: " + zoomLevel + "");
        } catch (Exception e) {
            Log.e(TAG, "Error updating preview: ", e);
        }
    }
}
